﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using System.Diagnostics;
namespace BlackBox.Models
{
    #region Player Class
    public class Player
    {
        public string Name { get; set; }
        public Player Opponent { get; set; }
        public bool IsPlaying { get; set; }
        public bool Turn { get; set; }
        public int Win { get; set; }
        public int Lose { get; set; }
        public string ConnectionId { get; set; }
    }
    #endregion

    public class GameHub : Hub
    {

        GameRepository repGame = new GameRepository();
        ScoreRepository repScore = new ScoreRepository();
        UserRepository repUser = new UserRepository();

        static List<Player> RegistedUsers = new List<Player>();
        static List<string> ConnectedUsers = new List<string>();

        #region Tasks
        //onConnection and onDisconnected are the same as in
        //Warrior Hub, look there for info
        public override Task OnConnected()
        {
            
            //On Start
            if (ConnectedUsers.Count == 0)
            {
                ActiveGame theGame = new ActiveGame();
                theGame.owner = Context.User.Identity.Name.ToString();
                theGame.id = repGame.GetIdByOwner(theGame);
                theGame.numberofplayers = 1;
                repGame.Update(theGame);
            }
            else
            {
                if (ConnectedUsers[0] == null)
                    return Clients.All.allThrow();
                else
                {
                    ActiveGame theGame = new ActiveGame();
                    theGame.owner = ConnectedUsers[0];
                    theGame.id = repGame.GetIdByOwner(theGame);
                    theGame = repGame.GetActiveGameById(theGame.id);
                    theGame.numberofplayers += 1;
                    repGame.Update(theGame);
                    if (theGame.numberofplayers == theGame.minplayers)
                        return Clients.All.readyToStart();
                }
            }

            if (!ConnectedUsers.Contains(Context.User.Identity.Name.ToString()))
            {
                Clients.All.callRegister();
                ConnectedUsers.Add(Context.User.Identity.Name.ToString());
            }

            return Clients.All.connected(Context.User.Identity.Name, ConnectedUsers);
        }

        public override Task OnDisconnected()
        {
            var deletePlayer = RegistedUsers.Where(x => x.ConnectionId == Context.ConnectionId).FirstOrDefault();
            
            if (deletePlayer != null)
            {
                RegistedUsers.Remove(deletePlayer);
            }

            ActiveGame theGame = new ActiveGame();

            if (ConnectedUsers.Count != 0)
            {
                theGame.owner = ConnectedUsers[0];
                theGame.id = repGame.GetIdByOwner(theGame);

                if (theGame.id == -1)
                {
                    ConnectedUsers.Remove(Context.User.Identity.Name.ToString());
                    return Clients.All.disconnected(Context.User.Identity.Name);
                }
            }
            else
            {
                return Clients.All.allThrow();
            }

            if (ConnectedUsers.Count != 0)
            {
                if (ConnectedUsers[0] == Context.User.Identity.Name)
                {
                    repGame.RemoveActiveGame(theGame.id);
                    ConnectedUsers.Remove(Context.User.Identity.Name.ToString());
                    return Clients.All.allThrow();
                }
                else
                {
                    theGame = repGame.GetActiveGameById(theGame.id);

                    theGame.numberofplayers -= 1;
                    repGame.Update(theGame);
                    ConnectedUsers.Remove(Context.User.Identity.Name.ToString());
                    return Clients.All.disconnected(Context.User.Identity.Name);
                }
            }
            else
            {
                repGame.RemoveActiveGame(theGame.id);
                ConnectedUsers.Remove(Context.User.Identity.Name.ToString());
                return Clients.All.allThrow();
            }
        }
        #endregion

        #region Game functions

        #region Register Client
        //Registering the Client
        public void RegisterClient()
        {
            if (RegistedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId) == null)
            {
                //Creating a player
                Player addPlayer = new Player();
                {
                    addPlayer.Name = Context.User.Identity.Name;
                    addPlayer.ConnectionId = Context.ConnectionId;
                    addPlayer.IsPlaying = false;
                    addPlayer.Turn = true;
                    addPlayer.Win = 0;
                    addPlayer.Lose = 0;
                };
                //Adding it to the list
                RegistedUsers.Add(addPlayer);
                //Alerting that the player has been registered
                Clients.All.registerDone(addPlayer.Name);
            }
        }
        #endregion

        #region Start Game
        //If RegistedUser contains 2 player the game will start 
        public void StartGame()
        {
            var player = RegistedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);

            if (player == null)
                return;

            var opponent = RegistedUsers.Where(x => x.ConnectionId != Context.ConnectionId).FirstOrDefault();

            if (opponent == null)
            {
                Clients.Client(Context.ConnectionId).testStart(false);
                return;
            }
            else
            {
                Clients.Client(Context.ConnectionId).testStart(true);
            }

            player.Opponent = opponent;
            opponent.Opponent = player;
        }
        #endregion

        #region Chat
        //Send Message to All (Loopy)
        public void SendMessage(string message)
        {
            string from = Context.User.Identity.Name;
            Clients.All.AddMessage(from, message);
        }
        #endregion

        #region Send Move
        //Send Move 
        public void SendMove(string message)
        {
            var player = RegistedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
            var opponent = RegistedUsers.Where(x => x.ConnectionId != Context.ConnectionId).FirstOrDefault();

            if (player.Turn)
            {
                player.Turn = false;
                opponent.Turn = true;
                //Send Move
                Clients.All.AddMove(message);
                //Tells the player who just moved to wait
                Clients.Client(Context.ConnectionId).playerWait();
                //Tells  the opponent that it is his turn
                Clients.Client(opponent.ConnectionId).playerGo();
            }
        }
        #endregion

        #region Load Game
        //Loading the Game
        public void LoadGame()
        {
            Clients.All.InsertGame();
        }
        #endregion

        #region Player Won
        //Player Won
        public void PlayerWon(bool flag)
        {
            Clients.All.AlertWin(flag);
            Clients.All.Clean();
        }
        #endregion

        #region Draw
        //Draw
        public void Draw()
        {
            Clients.All.alertDraw();
            Clients.All.Clean();
        }
        #endregion

        #region Update Game
        //Updating the game and logging scoure
        public void GameUpdate(bool flag)
        {
            var player = RegistedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);

            UserProfiles userPlayer = repUser.GetByName(player.Name);

            ActiveGame theGame = new ActiveGame();
            theGame.owner = ConnectedUsers[0];
            theGame.id = repGame.GetIdByOwner(theGame);
            theGame = repGame.GetActiveGameById(theGame.id);


            ScoreBoard playerScore;

            //Check it the score board exists if it does not it is created
            if (!repScore.checkIfScoreExists(userPlayer.UserId, theGame.gameid))
            {
                repScore.CreateNewUserGameScore(userPlayer.UserId, theGame.gameid);
                playerScore = repScore.getScoreByGame(userPlayer.UserId, theGame.gameid);
            }
            else
            {
                playerScore = repScore.getScoreByGame(userPlayer.UserId, theGame.gameid);
            }

            if (flag)
            {
                playerScore.win += 1;
            }
            else
            {
                playerScore.loss += 1;
            }

            //Updating the Score board
            //repScore.UpdateUserGameScore(playerScore);
    
        }
        #endregion

        #endregion
    }
}